/*
 * twi_master.c
 *
 *      Author: Christian
 *      Letztes Update: 03.11.13 Christian | Code Aufräumen
 *
 */

#include "twi_master.h"

/* TWI stop Methode
 * Kein Return wert. Beendet TWI
 */
void twi_stop(void) {

	TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
	while ((TWCR & (1 << TWSTO)))
		;
}

/* TWI Initialisierung
 * Frequenz anpassen
 */
void twi_init(void) {
	PORTC |= (1 << PC0) | (1 << PC1);

	TWSR = 0;
	TWBR = (( CPU / F_I2C) - 16) / 2;

}

/* TWI  Adresse senden
 * ausgelagerte Funktion fuer die twi_start Funktion
 *
 * Adresse definieren
 *
 * return 1 bei Erfolg
 */
static uint8_t twi_send_adr(uint8_t adresse) {

	TWDR = adresse;
	TWCR = (1 << TWINT) | (1 << TWEN);

	while (!( TWCR & (1 << TWINT)))
		;

	if (( TWSR & 0xF8) == !( TW_MT_SLA_ACK) && !( TW_MR_SLA_ACK)) {
		return 0;
	}
	return 1;
}

/* TWI start senden
 *
 * return 1 bei Erfolg
 */
uint8_t twi_start(uint8_t adresse) {

	TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
	while (!( TWCR & (1 << TWINT)))
		;

	if (( TWSR & 0xF8) != TW_START) {
		return 0;
	}

	return twi_send_adr(adresse);

}

/* TWI repstart senden
 *
 * return 1 bei erfolg
 */
uint8_t twi_repstart(uint8_t adresse) {

	TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN);
	while (!( TWCR & (1 << TWINT)))
		;

	if (( TWSR & 0xF8) != TW_REP_START) {
		return 0;
	}

	return twi_send_adr(adresse);
}

/* Datenbyte senden
 * Adresse muss erfolgreich gesendet worden sein
 *
 * return 1 bei Erfolg
 */
uint8_t twi_send_data(uint8_t data) {

	TWDR = data;
	TWCR = (1 << TWINT) | (1 << TWEN);

	while (!( TWCR & (1 << TWINT)))
		;

	if ((TWSR & 0xF8) != TW_MT_DATA_ACK) {
		return 0;
	}
	return 1;
}

/*TWI Datenbyte empfangen
 * Start Impuls und Adresse muessen gesendet sein
 * nach Empfang kommt stop impuls
 *
 */
uint8_t twi_recieve_data_nack(void) {

	TWCR = (1 << TWINT) | (1 << TWEN);
	while (!( TWCR & (1 << TWINT)))
		;

	return TWDR;

}

/*TWI Datenbyte empfangen
 * Start Impuls und Adresse muessen gesendet sein
 * nach Empfang kommt  KEIN stop impuls
 * */
uint8_t twi_recieve_data_ack(void) {

	TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA);
	while (!( TWCR & (1 << TWINT)))
		;

	return TWDR;

}
